package com.atguigu.gmall.activity.receiver;

import com.atguigu.gmall.activity.model.SeckillGoods;
import com.atguigu.gmall.activity.service.SeckillGoodsService;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.rabbitmq.client.Channel;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.BoundListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.Date;
import java.util.List;

/**
 * title:
 * author: Gyh
 * date:2023-05-14 10:22
 * Description:
 */
@Slf4j
@Component
public class ActivityReceiver {

    @Autowired
    private SeckillGoodsService seckillGoodsService;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 监听秒杀商品预热消息
     *  查询数据库中当日参与秒杀的商品列表
     *  导入到分布式缓存中
     * @param channel
     * @param message
     */
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_TASK,durable = "true"),
            value = @Queue(value = MqConst.QUEUE_TASK_1,durable = "true"),
            key = MqConst.ROUTING_TASK_1
    ))
    public void processSeckillGoodsImport(Channel channel, Message message){
        try {
            log.info("[秒杀法务]监听到秒杀商品入库消息");
            //查询数据库中当日参与秒杀的商品列表
            LambdaQueryWrapper<SeckillGoods> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SeckillGoods::getStatus,"1");
            queryWrapper.gt(SeckillGoods::getStockCount,0);
            String today = DateUtil.formatDate(new Date());
            //增加自定义sql语句
            queryWrapper.apply("date_format(start_time,'%Y-%m-%d') = '" + today + "'");
            List<SeckillGoods> seckillGoodsList = seckillGoodsService.list(queryWrapper);
            if (!CollectionUtils.isEmpty(seckillGoodsList)){
                //导入到分布式缓存中
                    //将参与秒杀商品批量保存到Redis,Hash数据类型
                        //1.创建秒杀商品Hash结构的Key
                String seckillGoodsKey = RedisConst.SECKILL_GOODS;
                        //2.创建hash操作对象
                BoundHashOperations<String,String,SeckillGoods> hashOps = redisTemplate.boundHashOps(seckillGoodsKey);
                seckillGoodsList.stream().forEach(seckillGoods -> {
                    if (!hashOps.hasKey(seckillGoods.getSkuId().toString())){
                        //3.使用秒杀商品列表存入redis中
                        hashOps.put(seckillGoods.getSkuId().toString(),seckillGoods);
                        //将每件参与秒杀的库存存入Redis,List数据类型
                        //创建商品库存list结构key
                        String seckillGoodsStockKey = RedisConst.SECKILL_STOCK_PREFIX+ seckillGoods.getSkuId();
                        //创建商品库存list操作对象
                        BoundListOperations<String,String> listOps = redisTemplate.boundListOps(seckillGoodsStockKey);
                        //遍历商品库存数量存入list
                        for (Integer i = 0; i < seckillGoods.getStockCount(); i++) {
                            listOps.leftPush(seckillGoods.getSkuId().toString());
                        }
                        //将导入秒杀商品状态存入每个秒杀服务实例本地缓存中,发送消息到Redis
                        redisTemplate.convertAndSend("seckillpush",seckillGoods.getSkuId()+":1");

                    }
                });
            }
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        } catch (IOException e) {
            e.printStackTrace();
            channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
        }
    }
}
